package com.jie.server.core.runnable;

import com.jie.common.http.constant.response.HttpResponseStatusConstant;
import com.jie.common.http.entity.request.HttpRequest;
import com.jie.common.http.entity.response.HttpResponse;
import com.jie.common.message.entity.Message;
import com.jie.common.ssl.constant.SslConstant;
import com.jie.common.ssl.util.AesUtil;
import com.jie.server.core.ServerApplication;
import com.jie.server.core.entity.ChannelAttachment;
import com.jie.server.core.handler.DispatchHandler;
import com.jie.server.core.handler.InterceptorHandler;
import com.jie.server.core.util.NioUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;

/**
 * 用于处理读的Runnable对象
 * @author XieZhiJie
 * @date 2022/04/22 12:05
 */
public class ReadHandlerRunnable implements Runnable {

    private final Logger logger = LoggerFactory.getLogger(ReadHandlerRunnable.class);

    private final SelectionKey key;

    public ReadHandlerRunnable(SelectionKey key) {
        this.key = key;
    }

    @Override
    public void run() {
        try {
            ServerApplication.SELECTION_KEY_THREAD_LOCAL.set(this.key);
            handleRead();
        } catch (Exception e) {
            logger.error(e.getMessage());
            NioUtil.closeKeyChannelAndCancel(this.key);
        } finally {
            ServerApplication.SELECTION_KEY_THREAD_LOCAL.remove();
        }
    }

    /**
     * 处理读事件
     * @throws Exception Exception
     */
    private void handleRead() throws Exception {
        SocketChannel socketChannel = (SocketChannel) this.key.channel();
        ChannelAttachment channelAttachment = (ChannelAttachment) this.key.attachment();
        ByteBuffer readByteBuffer = channelAttachment.getReadByteBuffer();
        do {
            // 1.获取bytes
            byte[] readBytes = NioUtil.readMessage(socketChannel, readByteBuffer);
            readBytes = AesUtil.decryptAndVerifyDigest(readBytes, channelAttachment.getAes(), SslConstant.OPEN_SSL);

            HttpRequest httpRequest;
            HttpResponse httpResponse;
            try {
                // 2.bytes转为request
                httpRequest = HttpRequest.getHttpRequest(readBytes);

                // 3.请求拦截
                // 拦截器
                if (InterceptorHandler.interceptor(this.key, httpRequest)) {
                    httpResponse = new HttpResponse(HttpResponseStatusConstant.FORBIDDEN);
                } else {
                    // 4.请求分发处理
                    httpResponse = DispatchHandler.dispatchRequestAndHandleRequest(httpRequest);
                }

            } catch (Exception e) {
                this.logger.warn("httpRequest解析失败!");
                httpResponse = new HttpResponse(HttpResponseStatusConstant.BAD_REQUEST);
            }

            // 5.写数据
            Message message = new Message();
            message.setMessageBytes(httpResponse.getMessageBytes());
            // 将数据挂到写队列上
            NioUtil.sendMessage(this.key, message);
        } while (readByteBuffer.position() > 0);
        channelAttachment.interestOps(this.key, this.key.interestOps() | SelectionKey.OP_READ);
    }

}
